package com.ashlikun.pdfview

import android.graphics.Bitmap
import android.os.Handler
import android.util.Log
import com.ashlikun.pdfview.exception.PageRenderingException
import com.ashlikun.pdfview.model.PagePart
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlin.math.roundToInt

/**
 * 作者　　: 李坤
 * 创建时间: 2024/7/5　11:08
 * 邮箱　　：496546144@qq.com
 *
 * 功能介绍： * 将处理传入的[RenderingTask]消息的[Handler]
 *  * 当的部分
 *  * PDF已准备好渲染.
 */
class RenderingJob(private val pdfView: PDFView) {
    companion object {
        private val TAG = RenderingJob::class.java.name
    }

    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

    private var running = false
    private val loadings = ArrayList<Int>()
    private val tasks = ArrayList<RenderingTask>()
    private val tasksLock = Any() as Object

    init {
        scope.launch {
            while (true) {
                val task = synchronized(tasks) { tasks.removeFirstOrNull() }
                if (task == null) {
                    synchronized(tasksLock) {
                        tasksLock.wait()
                    }

                } else {
//                    Util.logi("消费者 接收到任务  ${task.page}")
                    handleTask(task)
                }
            }
        }
    }

    fun cleanTask() {
        synchronized(tasks) {
            tasks.clear()
        }
    }

    fun stop() {
        running = false
        synchronized(tasks) {
            tasks.clear()
        }
        synchronized(tasksLock) {
            tasksLock.notifyAll()
        }
        synchronized(loadings) {
            loadings.clear()
        }
        scope?.cancel()
    }

    fun start() {
        loadings.clear()
        running = true
    }

    private fun handleTask(task: RenderingJob.RenderingTask) {
        try {
            if (running) {

                val part = proceed(task)
                if (part != null) {
                    if (running) {
                        pdfView.post {
                            //内部添加进缓存了
                            pdfView.onBitmapRendered(part)
                            //清除加载中,线程安全
                            synchronized(loadings) { loadings.remove(task.page as Any) }
                        }
                    } else {
                        part.bitmap.recycle()
                    }
                }
            }
        } catch (ex: PageRenderingException) {
            pdfView.post { pdfView.onPageError(ex) }
        }
    }

    @Throws(PageRenderingException::class)
    private fun proceed(renderingTask: RenderingTask): PagePart? {
        synchronized(loadings) {
            if (loadings.contains(renderingTask.page)) return null
            loadings.add(renderingTask.page)
        }
        val pdfFile = pdfView.pdfFile
        pdfFile!!.openPage(renderingTask.page)
        val w = renderingTask.width.roundToInt()
        val h = renderingTask.height.roundToInt()
        if (w == 0 || h == 0 || pdfFile.pageHasError(renderingTask.page)) {
            return null
        }
//        Util.logi("消费者 proceed start  page=${renderingTask.page}")
        val render = try {
            if (pdfFile.isSystemRenderer) Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
            else Bitmap.createBitmap(w, h, if (renderingTask.bestQuality) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565)
        } catch (e: IllegalArgumentException) {
            Log.e(TAG, "Cannot create bitmap", e)
            return null
        }
//        Util.logi("消费者 proceed end page=${renderingTask.page}")
        pdfFile.renderPageBitmap(render, renderingTask.page, w, h, renderingTask.annotationRendering)
        return PagePart(renderingTask.page, renderingTask.zoom, render)
    }

    fun addRenderingTask(page: Int, width: Float, height: Float, bestQuality: Boolean, annotationRendering: Boolean, zoom: Float) {
//        Util.logi("生产者 添加任务  ${page}")
        val task = RenderingTask(width, height, page, bestQuality, annotationRendering, zoom)
        synchronized(tasks) {
            tasks.add(task)
        }
        synchronized(tasksLock) {
            tasksLock.notifyAll()
        }
    }


    private inner class RenderingTask constructor(var width: Float, var height: Float, var page: Int, var bestQuality: Boolean, var annotationRendering: Boolean, val zoom: Float)

}